#include "inputmanager.h"
#include <mmsystem.h>
#pragma comment (lib, "winmm.lib")

/**
 * Ustawia aktualne urzadzenie wejsciowe
 *
 * @return True jesli urzadzenie jest podlaczone do systemu; false jesli nie.
 */
bool InputManager::setDevice(Device dev)
{
	if(!checkDevice(dev))
		return false;
	device = dev;
	reset();
	return true;
}


/**
 * Sprawdza gotowosc urzadzenia wejsciowego
 *
 * @return True jesli urzadzenie jest podlaczone do systemu; false jesli nie.
 */
bool InputManager::checkDevice(Device dev)
{
	switch(dev)
	{
	case KeyboardArrows:
	case KeyboardWSAD:
		return true;
	case Joystick1:
		return joy1Attached;
	case Joystick2:
		return joy2Attached;
	default:
		return false;
	}
}


/**
 * Inicjalizuje menedzera wejscia dla danego okna
 *
 * @param hWnd Uchwyt okna
 * @return True jesli inicjalizacja sie powiedzie; false jesli nie.
 */
bool InputManager::initialize(HWND hWnd)
{
	JOYINFO joyInfo;
	UINT numDevs;

	// podlacz joystick-i
    if((numDevs = joyGetNumDevs()) == 0)
	{
		// brak joystick-ow
		joy1Attached = joy2Attached = false;
        return true;
	}

    joy1Attached = (joyGetPos(JOYSTICKID1, &joyInfo) != JOYERR_UNPLUGGED);
    joy2Attached = (numDevs == 2) &&
		(joyGetPos(JOYSTICKID2, &joyInfo) != JOYERR_UNPLUGGED);

	if(joy1Attached)
		if(JOYERR_NOERROR != joySetCapture(hWnd, JOYSTICKID1, 10, FALSE))
			joy1Attached = false; // blad - wylacz
	if(joy2Attached)
		if(JOYERR_NOERROR != joySetCapture(hWnd, JOYSTICKID2, 10, FALSE))
			joy2Attached = false; // blad - wylacz

	return true;
}


/**
 * Zamyka menedzera wejscia
 */
void InputManager::close()
{
	if(joy1Attached)
		joyReleaseCapture(JOYSTICKID1);
	if(joy2Attached)
		joyReleaseCapture(JOYSTICKID2);
}


/**
 * Resetuje stan urzadzenia wejsciowego i przygotowuje je
 * do odebrania danych.
 */
void InputManager::reset()
{
	state.reset();
}


/**
 * Odbiera dane z komunikatu okna WinAPI
 *
 * @param msg Komunikat
 * @param wParam Parametr 1
 * @param lParam Parametr 2
 * @return True jesli komunikat zostal przetworzony; false jesli nie.
 */
bool InputManager::processInput(UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(device)
	{

	case KeyboardArrows:
		switch(msg)
		{
		case WM_KEYDOWN:
			switch(wParam)
			{
			case VK_UP:
				state.up = 1.0f;
				return true;
			case VK_DOWN:
				state.down = 1.0f;
				return true;
			case VK_LEFT:
				state.left = 1.0f;
				return true;
			case VK_RIGHT:
				state.right = 1.0f;
				return true;
			}
			return false;

		case WM_KEYUP:
			switch(wParam)
			{
			case VK_UP:
				state.up = 0.0f;
				return true;
			case VK_DOWN:
				state.down = 0.0f;
				return true;
			case VK_LEFT:
				state.left = 0.0f;
				return true;
			case VK_RIGHT:
				state.right = 0.0f;
				return true;
			}
			return false;
		}

	case KeyboardWSAD:
		switch(msg)
		{
		case WM_KEYDOWN:
			switch(wParam)
			{
			case 'W':
				state.up = 1.0f;
				return true;
			case 'S':
				state.down = 1.0f;
				return true;
			case 'A':
				state.left = 1.0f;
				return true;
			case 'D':
				state.right = 1.0f;
				return true;
			}
			return false;

		case WM_KEYUP:
			switch(wParam)
			{
			case 'W':
				state.up = 0.0f;
				return true;
			case 'S':
				state.down = 0.0f;
				return true;
			case 'A':
				state.left = 0.0f;
				return true;
			case 'D':
				state.right = 0.0f;
				return true;
			}
			return false;
		}

	case Joystick1:
		switch(msg)
		{
		case MM_JOY1MOVE:
			float x = 1.0f - ((float)LOWORD(lParam)) / ((float)0x7FFF);
			float y = 1.0f - ((float)HIWORD(lParam)) / ((float)0x7FFF);
			if(x > 0)
			{
				state.left = x;
				state.right = 0.0f;
			}
			else 
			{
				state.left = 0.0f;
				state.right = -x;
			}
			if(y > 0)
			{
				state.up = y;
				state.down = 0.0f;
			}
			else
			{
				state.up = 0.0f;
				state.down = -y;
			}
			return true;
		}
		return false;

	case Joystick2:
		switch(msg)
		{
		case MM_JOY2MOVE:
			float x = 1.0f - ((float)LOWORD(lParam)) / ((float)0x7FFF);
			float y = 1.0f - ((float)HIWORD(lParam)) / ((float)0x7FFF);
			if(x > 0)
			{
				state.left = x;
				state.right = 0.0f;
			}
			else 
			{
				state.left = 0.0f;
				state.right = -x;
			}
			if(y > 0)
			{
				state.up = y;
				state.down = 0.0f;
			}
			else
			{
				state.up = 0.0f;
				state.down = -y;
			}
			return true;
		}
		return false;
	};
	return false;
}
